<?php
/**
 * 
 * 
 * @version $Id: CParameterArray.php,v 1.2 2011-05-29 05:37:28 herve Exp $
 * @copyright 2011
 */
class CParameterArray extends CComponent implements ArrayAccess, IteratorAggregate, Countable {

	protected $_headersByMnemonic = array ();
	protected $_headersByIndex = array ();

	protected $_rowsValues = null;
	protected $_rowsValuesByKey = null;
	protected $_columnsValues = null;

	protected $_iterationMode;

	public function __construct($headers = null, $values = null) {
		$this->_rowsValues = new CParameterList();
		$this->_rowsValuesByKey = new CParameterList();
		$this->_columnsValues = new CParameterList();
		$this->_iterationMode = CParameterIterator::$ROW_ITERATION;
		
		if ($headers !== null && is_array($headers)) {
			// TODO Multiple columns key !
			$key = null;
			foreach ($headers as $header) {
				$this->_headersByMnemonic[$header['mnemonic']] = $header;
				$this->_headersByIndex[$header['index']] = & $this->_headersByMnemonic[$header['mnemonic']];
				$this->_columnsValues[$header['mnemonic']] = new CParameterIndexedList($header['mnemonic']);
				if ($header['key']) $key = $header;
			}

			if ($values !== null && is_array($values)) {
				foreach ($values as $row => $row_values) {
					$this->_rowsValues[$row] = new CParameterRow();
					foreach ($row_values as $column => $value) {
						if (isset ($this->_headersByIndex[$column])) {
							$this->_rowsValues[$row][$column] = & $value;
							$this->_columnsValues[$column][$row] = & $this->_rowsValues[$row][$column];
						}
					}
					if ($key != null)
						$this->_rowsValuesByKey[$this->_rowsValues[$row][$key['index']]] = & $this->_rowsValues[$row];
				}
			}
		}
	}

	public function headers() {
		return $this->_headersByMnemonic;
	}

	public function values() {
		return $this->_rowsValues;
	}

	// Called by isset()
	public function offsetExists($offset) {
		if (gettype($offset) === 'string') {
			// string => return the column
			return isset ($this->_columnsValues[$offset]);
		} else
			if (gettype($offset) === 'integer') {
				// integer => return the row
				return isset ($this->_rowsValues[$offset]);
			}
		return false;
	}

	// Find value
	public function offsetGet($offset) {
		$r = null;
		if (gettype($offset) === 'string') {
			// string => return the column
			$r = $this->_columnsValues[$offset];
		} else
			if (gettype($offset) === 'integer') {
				// integer => return the row
				$r = $this->_rowsValues[$offset];
			}
		return $r;
	}

	// Value update
	public function offsetSet($offset, $value) {
		$r = null;
		if (gettype($offset) === 'string') {
			// string => return the column
			if (is_array($value))
				$value = new CParameterIndexedList($offset, $value);

			if ($value instanceof CParameterIndexedList) {
				$this->_columnsValues[$offset] = $value;
				$r = $this->_columnsValues[$offset];
			}
		} else
			if (gettype($offset) === 'integer') {
				// integer => return the row
				if (is_array($value))
					$value = new CParameterIndexedList($offset, $value);

				if ($value instanceof CParameterIndexedList) {
					$this->_rowsValues[$offset] = $value;
					$r = & $this->_rowsValues[$offset];
				}
			}
		return $r;
	}

	// If call to unset()
	public function offsetUnset($offset) {
		if (gettype($offset) === 'string') {
			// string => return the column
			$header = $this->_headersByMnemonic[$offset];
			unset ($this->_columnsValues[$offset]);
			unset ($this->_headersByMnemonic[$offset]);
			unset ($this->_headersByIndex[$header['index']]);
			foreach ($this->_rowsValues as $idx => $row) {
				unset ($row[$header['index']]);
				$this->_rowsValues[$idx] = $row;
			}
		} else
			if (gettype($offset) === 'integer') {
				unset ($this->_rowsValues[$offset]);
				foreach ($this->_columnsValues as $idx => $row) {
					unset ($row[$offset]);
					$this->_columnsValues[$idx] = $row;
				}
			}
	}

	public function getHeaders() {
		return $this->_headersByMnemonic;
	}

	public function getValues() {
		return $this->_rowsValues;
	}

	public function getIndices() {
		return $this->_rowsValues->getKeys();
	}
	
	public function iterateOnRow(){
		$this->_iterationMode = CParameterIterator::$ROW_ITERATOR;
	}

	public function iterateOnCol(){
		$this->_iterationMode = CParameterIterator::$COL_ITERATOR;
	}
	
	public function getIterator() {
		return new CParameterIterator($this, $this->_iterationMode);
	}

	public function count() {
		return count($this->_headersByMnemonic);
	}

	public function __clone() {
		$class = get_class($this);
		return new $class ($this->headers(), $this->values());
	}
	
	public function toAssociativeArray()
	{
		return $this->_rowsValuesByKey;
	}

}
?>
